home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 43.zip / Sources C- WorkDisk V.adf / ex / scales.c < prev    next >
C/C++ Source or Header  |  1987-02-15  |  18KB  |  614 lines

  1. /*Article 1491 of net.micro.amiga:
  2. Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site well.UUCP
  3. Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site well.UUCP
  4. Path: well!crunch
  5. From: crunch@well.UUCP (John Draper)
  6. Newsgroups: net.micro.amiga
  7. Subject: scale.c by Steven A. Bennett from BIX
  8. Message-ID: <468@well.UUCP>
  9. Date: 11 Jan 86 11:26:06 GMT
  10. Date-Received: 11 Jan 86 11:26:06 GMT
  11. Reply-To: crunch@well.UUCP (John Draper)
  12. Organization: Whole Earth 'Lectronic Link, Sausalito, CA
  13. Lines: 596
  14. */
  15.  
  16. /* SCALES
  17.  *
  18.  *   by Steven A. Bennett
  19.  *
  20.  *   This program demonstrates the use of the Audio functions
  21.  * in the "ROM" to produce four voice sound.  It uses a simple
  22.  * waveform (sawtooth) with no amplitude control (ie, envelope)
  23.  * or frequency variation (ie, vibrato), but these can easily be
  24.  * implemented through the use of setpv(), below.
  25.  * This program may be freely distributed.
  26.  *
  27.  * NOTES
  28.  *
  29.  *   - This program was written fairly quickly, without the aid
  30.  * of the ROM Kernal Manual (save about 10 pages of notes copied
  31.  * from my dealer's copy).  Therefore, if anyone sees anything too
  32.  * much out of the ordinary, bear with it.  (Particularly in mind
  33.  * is CreatePort(), of whose use I inferred from several programs
  34.  * I have downloaded from both BIX and CompuServe)  Furthermore, this
  35.  * particular implementation was written with a full blown music
  36.  * driver in mind, therefore, some code may seem ineffecient, for
  37.  * the sake of speed.  Finally, I tend to get a bit sloppy when i'm
  38.  * working past midnight, so there may be some messy areas.
  39.  *
  40.  * REVISIONS
  41.  *
  42.  *   12/25/85 - Single voice driver written. (SAB)
  43.  *   12/26/85 - Multi-voice capability added. (SAB)
  44.  *   12/28/85 - Error handling refined (see FinishProg()) (SAB)
  45.  *   12/30/85 - Fixed cleanup routine. (SAB)
  46.  *    1/10/86 - Mod to work with Both Manx and Lattice - crunch@well.UUCP
  47.  *
  48.  */
  49.  
  50. #include "exec/types.h"
  51. #include "exec/memory.h"
  52. #include "devices/audio.h"
  53. #include "stdio.h"
  54.  
  55. #define  PRIORITY          10L    /* Priority for Audio Channel usage */
  56. #define  NBR_IOA_STRUCTS   10L    /* Number of IOAudio structures used */
  57. #define  PV_IOA_STRUCT     0L     /* index to ioapv struct */
  58. #define  FIN_IOA_STRUCT    9L     /* index to finishioa struct */
  59. #define  BIG_WAVE          256L   /* size of biggest waveform */
  60. #define  NBR_WAVES         7L     /* number of waves per instrument */
  61. #define  WAVES_TOTAL       1024L  /* alloc size for instrument's waves */
  62. #define  YES               1L
  63. #define  NO                0L
  64.  
  65. extern struct MsgPort *CreatePort();
  66. extern void *AllocMem();
  67.  
  68. UBYTE aMap[] = { 0x0f };                  /* allocate four channels */
  69. long  voiceMap[] = { 1, 2, 4, 8 };
  70. struct IOAudio *ioa, *finishioa, *ioapv;
  71. struct IOAudio *ioainuse[4];
  72. struct IOAudio *freeioa[4];
  73. long unitno = 1;
  74. int error;
  75. int waiting[4] = { NO, NO, NO, NO };
  76. int woffsets[] =
  77.    { 0, 256, 384, 448, 480, 496, 504, 508, 510 };
  78. int wlen[] =
  79.    { 256, 128, 64, 32, 16, 8, 4, 2, 1 };
  80. int perval[] =
  81.    { 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, 214 };
  82. BYTE *wptr;
  83. BYTE *owptr[4] = { NULL, NULL, NULL, NULL };
  84.  
  85. char *portstring[] = {
  86.    "Audio one",
  87.    "Audio two",
  88.    "Audio three",
  89.    "Audio four",
  90.    "Audio five",
  91.    "Audio six",
  92.    "Audio seven",
  93.    "Audio eight" };              /* names for the CreatePorts */
  94.  
  95. /* InitIOA()
  96.  *   This function initializes all IOAudio structures used by this
  97.  * program.
  98.  *
  99.  * NOTES
  100.  *   This version sets up enough IOAudio structures for four voices, plus
  101.  * a ADCMD_FINISH and an ADCMD_PERVOL, which are both synchronous.
  102.  * The ioainuse array is assumed to be the IOAudio structure which is
  103.  * being used by the current CMD_WRITE command for each voice.  The freeioa
  104.  * array is there so that no <click> is made when switching CMD_WRITEs.
  105.  * (ie., for speed)  Since the pointers are swapped when the switch occurs,
  106.  * one can always make the same assumption.  Note that ALL of the
  107.  * asynchronous (ie., ioainuse and freeioa) structures ought to have a
  108.  * unique ReplyPort (or so I think).  The IOAudio structure used to
  109.  * Open the Device must also have a ReplyPort, but it may not have to be
  110.  * unique.  I am taking no chances, however.
  111.  */
  112.  
  113. InitIOA()
  114.    {
  115.    int i;
  116.  
  117.    /* alloc the IOAudio structures
  118.     */
  119.    ioa = (struct IOAudio *)AllocMem((NBR_IOA_STRUCTS * (long)sizeof(*ioa)),
  120.       MEMF_PUBLIC | MEMF_CLEAR);
  121.    if (ioa == NULL)
  122.       FinishProg(1);
  123.  
  124.    /* set the various IOAudio structure pointers
  125.     */
  126.    for (i = 0; i < 4; ++i)
  127.       {
  128.       ioainuse[i] = &ioa[i + 1];
  129.       freeioa[i] = &ioa[i + 5];
  130.       }
  131.    ioapv = &ioa[PV_IOA_STRUCT];
  132.    finishioa = &ioa[FIN_IOA_STRUCT];
  133.  
  134.    /* Open the Audio Device.  This requires a ReplyPort, so we'll
  135.     * make it now, and reuse it later as part of ioapv, although it
  136.     * doesn't need one.  aMap[] is an array containing sets of
  137.     * bitmaps which allow various combinations of voices to be allocated.
  138.     * since we want all four voices, there is only one combination which
  139.     * will serve.
  140.     */
  141.    ioa->ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
  142.    ioa->ioa_Request.io_Message.mn_ReplyPort =
  143.       CreatePort("Audio zero", 0L);
  144.    if (ioa->ioa_Request.io_Message.mn_ReplyPort == NULL)
  145.       FinishProg(2);
  146.    ioa->ioa_Data = aMap;
  147.    ioa->ioa_Length = (long)sizeof(aMap);
  148.    error = OpenDevice(AUDIONAME, 0L, ioa, 0L);
  149.    if (error)
  150.       FinishProg(3);
  151.  
  152.    /* setup the finishioa and ioapv structs.  The IOF_QUICK flag
  153.     * makes them synchronous in all cases.
  154.     */
  155.    *finishioa = *ioa;
  156.    finishioa->ioa_Request.io_Flags = IOF_QUICK;
  157.    ioapv->ioa_Request.io_Flags = IOF_QUICK;
  158.  
  159.    finishioa->ioa_Request.io_Command = ADCMD_FINISH;
  160.    ioapv->ioa_Request.io_Command = ADCMD_PERVOL;
  161.  
  162.    /* setup the ioainuse and freeioa struct arrays.  All eight of
  163.     * them must have unique ReplyPorts, hence the CreatePort()s
  164.     * below.  portstring contains different port names for the
  165.     * eight ports.  (I have no idea as to what the zero in the
  166.     * CreatePort is used for, so don't ask.)
  167.     */
  168.    for (i = 0; i < 4; ++i)
  169.       {
  170.       *freeioa[i] = *ioa;
  171.       *ioainuse[i] = *ioa;
  172.       freeioa[i]->ioa_Request.io_Message.mn_ReplyPort =
  173.          CreatePort(portstring[i], 0L);
  174.       ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort =
  175.          CreatePort(portstring[i + 4], 0L);
  176.       }
  177.    for (i = 0; i < 4; ++i)
  178.       if (freeioa[i]->ioa_Request.io_Message.mn_ReplyPort == NULL ||
  179.          ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort == NULL)
  180.          FinishProg(4);
  181.    }
  182.  
  183. /* FinishProg(finishcode)
  184.  *    int finishcode;
  185.  *
  186.  *    displays an error message, if necessary, based on the value
  187.  * of finishcode, frees all allocated stuff (again based on finishcode)
  188.  * and then exits.
  189.  *
  190.  * NOTES
  191.  *   This is basically a tidy little "clean up" routine used by all exit
  192.  * routines in this program.  Since all the allocated "stuff" is supposed
  193.  * to be in global variables, freeing it up in one global location is
  194.  * much easier then doing it elsewhere.
  195.  *
  196.  */
  197.  
  198. char *errormsgs[] = {
  199.    "Finished!\n",
  200.    "Cannot allocate memory for IOAudio structures\n",
  201.    "Cannot create ReplyPort for OpenDevice call\n",
  202.    "Cannot open Audio Device\n",
  203.    "Cannot create ReplyPort(s) for remaining IOAudio structures\n",
  204.    "Cannot allocate memory for waveform\n",
  205.    "If you see this during execution, execute the programmer.\n" };
  206.  
  207. FinishProg(finishcode)
  208.    int finishcode;
  209.    {
  210.    int i;
  211.  
  212.    printf(errormsgs[finishcode]);
  213.    switch(finishcode)
  214.       {
  215.    case 0:
  216.       /* free up the WaveNode list
  217.        * (currently, just wptr)
  218.        */
  219.       FreeMem(wptr, WAVES_TOTAL);
  220.  
  221.    case 4:
  222.    case 5:
  223.       /* free up all ReplyPorts save the first.  Since we could be
  224.        * here due to an error in allocating same, we check first.
  225.        * (And yes, Virginia, we do fall through here)
  226.        */
  227.       for (i = 0; i < 4; ++i)
  228.          {
  229.          if (freeioa[i]->ioa_Request.io_Message.mn_ReplyPort)
  230.             DeletePort(freeioa[i]->ioa_Request.io_Message.mn_ReplyPort);
  231.          if (ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort)
  232.             DeletePort(ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort);
  233.          }
  234.  
  235.       /* Close the Audio Device
  236.        */
  237.       CloseDevice(ioa);
  238.  
  239.    case 3:
  240.       /* Delete the first ReplyPort
  241.        */
  242.       DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
  243.  
  244.    case 2:
  245.       /* Free the ioa memory
  246.        */
  247.       FreeMem(ioa, (NBR_IOA_STRUCTS * (long)sizeof(*ioa)));
  248.  
  249.       }
  250.    if (finishcode)
  251.       exit(1L);
  252.    exit(0L);
  253.    }
  254.  
  255. /* setwpv()
  256.  *
  257.  *   starts a sound on the channel specified by the global variable
  258.  * unitno.  By swapping between two IOAudio structures, this routine
  259.  * is able to accomplish it's task without a noticeable delay.
  260.  *
  261.  * NOTES
  262.  *   This routine should only be used when a waveform change is
  263.  * required, either due to frequency going out of the range of the
  264.  * existing waveform, or a different waveform has been chosen.  In
  265.  * most cases, setpv() will be sufficient.  Also, don't complain about
  266.  * the usage of io_Unit.  I didn't like it either.
  267.  *
  268.  */
  269.  
  270. setwpv(wf, len, per, vol, voice)
  271.    char *wf;
  272.    int len, per, vol, voice;
  273.    {
  274.    struct IOAudio *tmpioa;
  275.  
  276.    /* the next three lines are probably unnecessary and can be
  277.     * done instead in InitIOA, but why take chances?
  278.     */
  279.    freeioa[voice]->ioa_Request.io_Command = CMD_WRITE;
  280.    freeioa[voice]->ioa_Request.io_Flags = ADIOF_PERVOL | IOF_QUICK;
  281.    freeioa[voice]->ioa_Cycles = 0;
  282.  
  283.    /* Assign the unit numbers to the (<ahem>) pointer?
  284.     */
  285.    freeioa[voice]->ioa_Request.io_Unit = (struct Unit *)unitno;
  286.    finishioa->ioa_Request.io_Unit = (struct Unit *)unitno;
  287.  
  288.    /* Set the parameters
  289.     */
  290.    freeioa[voice]->ioa_Data = (UBYTE *)wf;
  291.    freeioa[voice]->ioa_Length = len;
  292.    freeioa[voice]->ioa_Period = per;
  293.    freeioa[voice]->ioa_Volume = vol;
  294.  
  295.    /* Terminate the old request, if there is one.  waiting[] is an
  296.     * boolean (well, pseudo-boolean) array stating if there was an
  297.     * old request.  The old CMD_WRITE must be finished, and the reply
  298.     * received, before the new CMD_WRITE will work.  I am not certain
  299.     * why this is necessary.  Originally, I tried a
  300.     *               BeginIO(freeioa[voice]);
  301.     *               BeginIO(finishioa);
  302.     *               WaitIO(ioainuse[voice]);
  303.     * series, but the net effect was that the freeioa request was
  304.     * ignored (without error), and the ioainuse request continued
  305.     * blindly onwards.  I had assumed that it would act as a FIFO queue,
  306.     * but apparently not.
  307.     */
  308.    if (waiting[voice])
  309.       {
  310.       BeginIO(finishioa);
  311.       WaitIO(ioainuse[voice]);
  312.       waiting[voice] = NO;
  313.       }
  314.  
  315.    /* now start up the new voice
  316.     */
  317.    BeginIO(freeioa[voice]);
  318.    error = CheckIO(freeioa[voice]);
  319.    if (error)
  320.       {
  321.       printf("Error on CMD_WRITE\n");
  322.       WaitIO(freeioa[voice]);
  323.       }
  324.    waiting[voice] = YES;
  325.  
  326.    /* swap the pointers.  That way, the next time we pass through, we
  327.     * will still work.
  328.     */
  329.    tmpioa = ioainuse[voice];
  330.    ioainuse[voice] = freeioa[voice];
  331.    freeioa[voice] = tmpioa;
  332.    }
  333.  
  334. /* setpv(per, vol)
  335.  *   int per, vol;
  336.  *
  337.  *   Changes the period and volume of the currently executing
  338.  * CMD_WRITE on the specified unitno.
  339.  *
  340.  * NOTES
  341.  *   This routine is perfect <ahem> as it is, both for single and
  342.  * multiple voices.  It can be used to change frequency, within limits,
  343.  * change volume, and simulate vibrato and envelope controls.
  344.  * For those of you wondering where I got my period values
  345.  * from, look in the ABASIC manual, page 138.  Or, if you wish, you
  346.  * can calculate it out for yourself using the formula:
  347.  *     period = C/(ns*hz)
  348.  *       - where C is the clock rate (3579545)
  349.  *               ns is the number of samples in a cycle of the wave
  350.  *               hz is the number of cycles per second.
  351.  * Thus, for middle A on the piano (440 hz) with 32 samples in the
  352.  * cycle of the waveform, one would get:
  353.  *     period = 3579545 / (32 * 440)
  354.  *            = 3579545 / 14080
  355.  *            = 254.229 (or pretty close)
  356.  * The period must be rounded to the nearest integer, which can result
  357.  * in a maximum frequency error of about .25%, assuming one uses the
  358.  * octave for frequency between period 226 and period 428.  (This comes
  359.  * out to be less than a twentieth step at the shortest period)
  360.  * period values of less than 127 are illegal, as there aren't enough
  361.  * cycles set aside for audio DMA for anything less.  period values of
  362.  * greater than 500 or so aren't recommended as the anti-aliasing
  363.  * filter isn't of much use then, and actually could cause a possible
  364.  * high pitched overtone, which I'm sure nobody wants.  Thus I am
  365.  * only going to use this to handle a single octave's range.
  366.  * Changes of octave are accomplished by doubling or halving the number
  367.  * of samples in one cycle of the waveform, and must, therefore, call
  368.  * setwpv().
  369.  */
  370.  
  371. setpv(per, vol)
  372.    int per, vol;
  373.    {
  374.    ioapv->ioa_Period = per;
  375.    ioapv->ioa_Volume = vol;
  376.    ioapv->ioa_Request.io_Unit = (struct Unit *)unitno;
  377.    BeginIO(ioapv);
  378.    }
  379.  
  380. /* StopVoices()
  381.  *
  382.  *   Terminates all CMD_WRITE routines in progress, effectively
  383.  * ending all sound.  Volume is set to zero first, just to be tidy.
  384.  *
  385.  */
  386.  
  387. StopVoices()
  388.    {
  389.    int voice;
  390.  
  391.    for (voice = 0; voice < 4; ++voice)
  392.       {
  393.       if (waiting[voice])
  394.          {
  395.          /* to stop a voice, we first set it's volume to zero
  396.           * (probably unnecessary) and then finish the CMD_WRITE.
  397.           */
  398.          unitno = voiceMap[voice];
  399.          setpv(128, 0);
  400.          finishioa->ioa_Request.io_Unit = (struct Unit *)unitno;
  401.          BeginIO(finishioa);
  402.          WaitIO(ioainuse[voice]);
  403.          waiting[voice] = NO;
  404.          }
  405.       }
  406.    }
  407.  
  408. /* setwave(wfp)
  409.  *   BYTE wfp;
  410.  *
  411.  *   this routine makes the first 256 bytes (lowest octave) of the
  412.  * sawtooth wave's waveform table.  wfp must have already been
  413.  * allocated and in CHIP MEMORY!!!  This is necessary later for the
  414.  * CMD_WRITE commands to work.
  415.  *   a sawtooth wave is a simple waveform, very easy to use.  It
  416.  * basically looks like this:
  417.  *
  418.  *     /|      /|      /|      /|
  419.  *    / |     / |     / |     / |
  420.  *   /  |    /  |    /  |    /  |
  421.  *  /   |   /   |   /   |   /   |
  422.  *      |  /    |  /    |  /    |  /
  423.  *      | /     | /     | /     | /
  424.  *      |/      |/      |/      |/
  425.  *
  426.  */
  427.  
  428. setwave(wfp)
  429.    UBYTE *wfp;          /* This is a sneaky way of making a sawtooth */
  430.    {
  431.    int i;
  432.  
  433.    for (i = 0; i < BIG_WAVE; ++i)
  434.       wfp[i] = i;
  435.    }
  436.  
  437. /* xpandwave(wfp)
  438.  *   BYTE *wfp;
  439.  *
  440.  * xpandwave expands a wave with only the base BIG_WAVE specified,
  441.  * into a set of NBR_WAVES waveforms, each for one octave.
  442.  * All of the waveforms are left in contiguous memory after the
  443.  * first wave, in order of decending sizes (256, 128, 64, ...)
  444.  *
  445.  * NOTES
  446.  *   Be forewarned that this function makes two assumptions.  The
  447.  * first is that there is enough memory in the wfp buffer to hold the
  448.  * expansion, and two, that the stuff is in chip mem.  (Actually,
  449.  * makewaves() makes that assumption instead.)  This function ought to
  450.  * work for any BIG_WAVE which is a power of two greater than 2^NBR_WAVES
  451.  *
  452.  */
  453.  
  454. xpandwave(wfp)
  455.    BYTE *wfp;
  456.    {
  457.    int i, j, rate;
  458.    BYTE *tptr;
  459.  
  460.    rate = 1;
  461.    tptr = wfp + BIG_WAVE;
  462.    for (i = 0; i < NBR_WAVES - 1; ++i)
  463.       {
  464.       rate *= 2;
  465.       for (j = 0; j < BIG_WAVE; j += rate)
  466.          *tptr++ = wfp[j];
  467.       }
  468.    }
  469.  
  470. /* makewaves()
  471.  *
  472.  *   just makes a sawtooth waveform in chip mem and expands it without
  473.  * the pretty list control and file IO stuff.
  474.  *
  475.  */
  476.  
  477. makewaves()
  478.    {
  479.    /* allocate the memory for the waveform.
  480.     */
  481.    wptr = (BYTE *)AllocMem(WAVES_TOTAL, MEMF_CHIP);
  482.    if (wptr == NULL)
  483.       FinishProg(5);
  484.  
  485.    /* get and expand the waveform
  486.     */
  487.    setwave(wptr);
  488.    xpandwave(wptr);
  489.    }
  490.  
  491. /* strike(note, voice)
  492.  *   int note, voice;
  493.  *
  494.  * This nice little routine takes a note and plays it on the given
  495.  * voice.  At a fixed amplitude.  The note is basically an integer from
  496.  * 0 to 11 (c to b) plus 12 per octave above the first and lowest.  It
  497.  * uses a pointer to the last waveform used by the voice specified to
  498.  * determine if it needs to call setwpv() or just setpv().  The waveform
  499.  * is used by adding an index (woffsets[]) dependant on the octave.
  500.  * the length of the waveform (in wlen[]) is likewise dependant on
  501.  * the octave.  Note that octaves start with zero, not one.
  502.  */
  503.  
  504. strike(note, voice)
  505.    int note, voice;
  506.    {
  507.    int per, oct, len;
  508.    BYTE *wfp;
  509.  
  510.    unitno = voiceMap[voice];
  511.    if (note >= 100)           /* play a rest. */
  512.       {
  513.       if (waiting[voice])
  514.          setpv(200, 0);
  515.       return;
  516.       }
  517.    oct = note / 12;
  518.    per = perval[note % 12];
  519.    wfp = wptr + woffsets[oct];
  520.  
  521.    /* if the waveform hasn't changed since the last strike,
  522.     * then only change the period.
  523.     */
  524.    if (wfp == owptr[voice])
  525.       setpv(per, 32);         /* fixed volume */
  526.    else
  527.       {
  528.       setwpv(wfp, wlen[oct], per, 32, voice);
  529.       owptr[voice] = wfp;
  530.       }
  531.    }
  532.  
  533. main()
  534.    {
  535.    int i, j;
  536.  
  537.    InitIOA();
  538.    makewaves();
  539.  
  540.    /* simple scale
  541.     */
  542.    for (i = 0; i < 24; ++i)
  543.       {
  544.       strike(i, 0);
  545.       Delay(10L);
  546.       }
  547.  
  548.    /* crossed scales
  549.     */
  550.    for (j = 48; i < 48; ++i, --j)
  551.       {
  552.       strike(i, 0);
  553.       strike(j, 1);
  554.       Delay(10L);
  555.       }
  556.  
  557.    /* crossed scales with lower in sync
  558.     */
  559.    for (j = 48; i < 72; ++i, --j)
  560.       {
  561.       strike(i, 0);
  562.       strike(i - 48, 1);
  563.       strike(j, 2);
  564.       Delay(10L);
  565.       }
  566.  
  567.    /* slow c chord...
  568.     */
  569.    strike(36, 0);
  570.    strike(100, 1);
  571.    strike(100, 2);
  572.    Delay(60L);
  573.    strike(40, 1);
  574.    Delay(60L);
  575.    strike(43, 2);
  576.    Delay(120L);
  577.  
  578.    /* ...and into a minor with the fourth voice
  579.     */
  580.    strike(46, 3);
  581.    Delay(200L);
  582.  
  583.    /* and two quick c chords to finish it up
  584.     */
  585.    restall();
  586.    Delay(20L);
  587.    cchord();
  588.    Delay(20L);
  589.    restall();
  590.    Delay(1L);
  591.    cchord();
  592.    Delay(200L);
  593.    StopVoices();
  594.    FinishProg(0);
  595.    }
  596.  
  597. restall()
  598.    {
  599.    int i;
  600.  
  601.    for (i = 0; i < 4; ++i)
  602.       strike(100, i);
  603.    }
  604.  
  605. cchord()
  606.    {
  607.    strike(36, 0);
  608.    strike(40, 1);
  609.    strike(43, 2);
  610.    strike(48, 3);
  611.    }
  612.  
  613.  
  614.